using DBEntitie;
using FrameWork;
using lhservice.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Threading.Tasks;
using lhservice.common;
using Hangfire;
using lhservice.common.websocket;
using System.Reflection;
using System.Configuration;
using log4net.Core;
using System.ServiceProcess;
using Newtonsoft.Json.Serialization;
using System.Net.Http;
using System.Net.Http.Headers;

namespace lhservice.Controllers
{
  /// <summary>
  /// 客服接口
  /// </summary>
  [Authorize]
  [ApiController]
  [Route("api/[controller]")]
  [AllowAnonymous]
  public class ServiceController : TimController
  {
    /// <summary>
    /// 新会话 自动推送消息
    /// </summary>
    /// <returns></returns>
    private string GetNotes()
    {

      List<Dictionary<string, dynamic>> res;
      using (var db = new SyBaseEntities())
      {
        string sql = "select * from notekf where getdate() > ddate_start and getdate()<= ddate_end";
        res = db.QueryTable(sql).ToList();
      }

      if (res.Count > 0)
      {
        string noteStr = "";

        foreach (var item in res)
        {
          noteStr += item["cnote"] + "\n";
        }
        return noteStr;
      }
      else
      {
        return "欢迎您咨询蓝华软件售后客服中心!我们的工作时间为9：00 - 18：00, 您也可以加我企业微信。\n客服正在接通中....";
      }
    }



    /// <summary>
    /// 生成一个会话
    /// </summary>
    /// <param name="openid"></param>
    /// <param name="cid"></param>
    /// <returns></returns>
    private Session GenSession(string openid, string cid)
    {
      var session = new Session();
      string sessionId = Guid.NewGuid().ToString();
      string cname = cid == "temp" ? "临时会话" : RegHelper.GetRegInfo(cid)["客户名称"];
      string ask = "";
      string sender = "";
      var now = DateTime.Now.ToLocalTime().ToString();
      using (var db = new SyBaseEntities())
      {
        var sql = $@"
          insert into z_session values(
            '{sessionId}',
            '{cid}',
            '{cname}',
            '{openid}',
            '{now}',
            null,
            null,
            1,
            '',
            0)";
        db.Execute(sql);

        sql = $@"select Ask,Sender from z_ask where openid='{openid}' and IsBind='N'";
        var t = db.QueryTable(sql).ToList();
        ask = t[0]["Ask"];
        sender = t[0]["Sender"];
        sql = $@"update z_ask set IsBind='Y',session_id='{sessionId}' where openid='{openid}' and IsBind='N'";
        db.Execute(sql);

        session.Session_id = sessionId;
        session.Customer_id = cid;
      }
      var sessionInfoItem = new Dictionary<string, string>()
      {
        ["session_id"] = sessionId,
        ["customer_id"] = cid,
        ["customer"] = cname,
        ["create_dt"] = now,
        ["Ask"] = ask,
        ["Sender"] = sender
      };
      var sessionInfo = new Dictionary<string, dynamic>()
      {
        [sessionId] = sessionInfoItem
      };
      WebsocketClientCollection.SendMessageToAll("newsession", JsonConvert.SerializeObject(sessionInfo));
      return session;
    }

    /// <summary>
    /// 获取 openid 未结束的会话
    /// session_state[0:已结束 1:等待接入会话 100:正在进行的会话]
    /// </summary>
    /// <param name="openid"></param>
    /// <returns></returns>
    private Session GetActiveSession(string openid)
    {
      var session = new Session();
      using (var db = new SyBaseEntities())
      {
        var sql = $@"select session_id,customer_id from z_session where openid = '{openid}' and session_state > 0 ";
        var table = db.QueryTable(sql);
        if (table != null)
        {
          foreach (DataRow row in table.Rows)
          {
            session.Session_id = row[0].ToString();
            session.Customer_id = row[1].ToString();
          }
        }
      }
      return session;
    }

    /// <summary>
    /// 通过openid 取 customerid
    /// </summary>
    /// <param name="openid"></param>
    /// <returns></returns>
    private string GetCustomerId(string openid)
    {
      var cid = "";
      using (var db = new SyBaseEntities())
      {
        var sql = $@"select customer_id from z_openid_bind_customer where openid = '{openid}'";
        var rows = db.FirstOrDefault(sql);
        cid = rows != null ? rows[0].ToString() : "";
      }
      return cid;
    }

    /// <summary>
    /// 微信客服推送消息中转路由 Ver 20230822
    /// </summary>
    /// <param name="msg"></param>
    private void MsgRouter(MsgOfSave msg)
    {
      // 获取 openid 未结束的会话
      var _openid = msg.FromUserName;
      var session = GetActiveSession(_openid);
      if (string.IsNullOrEmpty(session.Customer_id))/*无会话记录*/
      {        
        if (!MpServiceHelper.CheckAskBindWithOpenid(_openid))
        {
          // 没有找到未绑定的ask,提示用户前往小程序登记
          // 系统忽略该消息     
          MpServiceHelper.SendMsgToCustomer(new MsgToCustomer
          {
            touser = msg.FromUserName,
            msgtype = "text",
            text = new MsgToCustomerText { content = "您尚未通过我司小程序登记待处理问题，客服无法接收到您的消息！" }
          });
          return;
        }

        // 创建新会话
        var cid = string.IsNullOrEmpty(msg.SessionFrom) ? GetCustomerId(msg.FromUserName) : msg.SessionFrom;
        session = GenSession(msg.FromUserName, cid);

        // 系统自动回复，欢迎提示    
        MpServiceHelper.SendMsgToCustomer(new MsgToCustomer
        {
          touser = msg.FromUserName,
          msgtype = "text",
          text = new MsgToCustomerText { content = GetNotes() }
        });
      }

      // 2：消息处理 2-1：图片消息，把图片下载到自己服务器，然后修改picurl
      if (msg.MsgType == "image")
      {
        msg.PicUrl = UploadHelper.DownloadImgFromMpUrl(msg.PicUrl);
      }

      // 3： 消息保存到数据库   
      msg.CustomerId = session.Customer_id;
      msg.SessionId = session.Session_id;
      msg.Dir = "c2s";
      MpServiceHelper.SaveMsg(msg);

      //消息转发给客服
      var clients = WebsocketClientCollection.GetClientList(session.Session_id);
      msg.SessionId = session.Session_id;

      var content = JsonConvert.SerializeObject(msg);
      WebsocketClientCollection.SendMessageToClientList(clients, "received", content);
    }

    /// <summary>
    /// 接收客户发送的客服消息（微信消息服务器推送）
    /// </summary>
    /// <returns></returns>
    [HttpPost("[action]"), HttpGet("[action]")]
    public dynamic WxPush()
    {
      if (Request.Method == "GET")
      {
        //验证微信消息推送请求
        return Request.Query["echostr"].ToString();
      }
      else
      {
        StreamReader sr = new StreamReader(Request.Body);
        string line = " ";
        string res = "";

        while (line != null)
        {
          line = sr.ReadLine();
          if (line != null)
          {
            res += line;
          }
        }

        var msg = JsonConvert.DeserializeObject<MsgOfSave>(res);
        MsgRouter(msg);
        //BackgroundJob.Enqueue(() => MsgRouter(msg));                
        return "success";
      }
    }

    [HttpPost("[action]")]
    public async Task<IActionResult> FinishSession([FromBody] Dictionary<string, string> data)
    {
      String sql = "";
      String aid = data["aid"];
      String rate = data["rate"];
      using (var db = new SyBaseEntities())
      {
        //1、关闭会话
        sql = $"select session_id from z_ask where aid = '{aid}'";
        var res = db.FirstOrDefault(sql);
        String _sessionid = res[0].ToString();
        MpServiceHelper.CloseSession(_sessionid);
        //2、 isbind状态 N：未绑定会话 - Y：已绑定会话 - C：已结束会话
        //    更新z_ask IsBind = "C" rate = data["rate"]
        sql = $"update z_ask set IsBind='C',rate = '{rate}' where aid = '{aid}'";
        db.Execute(sql);

        sql = $@"select 
                aid,Ask,openid,IsBind,session_id,Sender,Phone,RemoteAccount,RemoteAuth,rate 
                  from z_ask where aid = '{aid}'";

        var clients = WebsocketClientCollection.GetClientList(_sessionid);
        var beClosed = new Dictionary<string, string>()
        {
          ["session_id"] = _sessionid
        };

        var content = JsonConvert.SerializeObject(beClosed);
        await WebsocketClientCollection.SendMessageToClientList(clients, "sessionClosed", content);

        return await PublicTool.ReturnSuccess(db.QueryTable(sql).ToList()[0]);
      }
    }


    [HttpPost("[action]")]
    public async Task<IActionResult> UpdateAsk([FromBody] Dictionary<string, string> data)
    {
      string aid = data["aid"];
      string sql = "";
      if (string.IsNullOrWhiteSpace(aid))
      {
        aid = Guid.NewGuid().ToString();
        sql = $@"insert into z_ask (aid,Sender,Phone,RemoteAccount,RemoteAuth,Ask,openid,IsBind) values          
          ('{aid}','{data["Sender"]}','{data["Phone"]}','{data["RemoteAccount"]}','{data["RemoteAuth"]}','{data["Ask"]}','{data["openid"]}','N')";
      }
      else
      {
        sql = $@"update z_ask set 
          Sender='{data["Sender"]}',
          Phone='{data["Phone"]}',
          RemoteAccount='{data["RemoteAccount"]}',
          RemoteAuth =  '{data["RemoteAuth"]}',
          Ask = '{data["Ask"]}' 
        where aid = '{data["aid"]}' ";
      }

      using (var db = new SyBaseEntities())
      {
        db.Execute(sql);
      }
      return await PublicTool.ReturnSuccess("ok");
    }


    [HttpGet("[action]")]
    public async Task<IActionResult> Abc()
    {
      using (var db = new SyBaseEntities())
      {
        var sql = "select cname from name";
        var t = db.QueryTable(sql);

      }
      return await PublicTool.ReturnSuccess("ok");
    }

    /// <summary>
    /// 获取消息记录表格创建SQL源码
    /// </summary>   
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> GetScripts()
    {
      var msg = new MsgOfSave();
      var res = new Dictionary<string, string>();
      var strs = "";
      foreach (PropertyInfo p in msg.GetType().GetProperties())
      {
        strs += $"{p.Name} ";
        strs += p.PropertyType == typeof(string) ? "varchar() null," : "integer null,";
      }
      res["create"] = strs;
      strs = "insert into z_service_msg (";
      bool isFirst = true;
      foreach (PropertyInfo p in msg.GetType().GetProperties())
      {
        strs += isFirst ? $"{p.Name}" : $",{p.Name}";
        if (isFirst) isFirst = false;
      }
      strs += ") values (";

      res["insert"] = strs;


      return await PublicTool.ReturnSuccess(res);
    }

    /// <summary>
    /// 获取客户注册信息
    /// </summary>
    /// <param name="cid"></param>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> GetRegInfo(string cid)
    {
      var res = RegHelper.GetRegInfo(cid);
      if (res.Count == 0)
      {
        return await PublicTool.ReturnError("客户编号无效!");
      }
      else
      {
        return await PublicTool.ReturnSuccess(res);
      }
    }

    [HttpGet("[action]")]
    public async Task<IActionResult> GetCustomInfo(string sid)
    {
      using (var db = new SyBaseEntities())
      {
        var sql = $@"select a.session_id,a.customer_id,a.customer,a.create_dt,b.Ask,b.Sender,b.Phone,b.RemoteAccount,RemoteAuth
                  from z_session a, z_ask b  
                    where a.session_id*=b.session_id and a.session_id = '{sid}'";
        return await PublicTool.ReturnSuccess(db.QueryTable(sql).ToList());
      }
    }

    /// <summary>
    /// 获取客服信息
    /// </summary>
    /// <param name="uid"></param>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> GetUserInfo(string uid)
    {
      var res = MpServiceHelper.GetUserInfo(uid);
      if (res.Count == 0)
      {
        return await PublicTool.ReturnError("客服编号无效!");
      }
      else
      {
        return await PublicTool.ReturnSuccess(res);
      }
    }

    [HttpGet("[action]")]
    public async Task<IActionResult> GetMsgList(string sid)
    {
      var res = MpServiceHelper.GetMsgList(sid);
      if (res.Count == 0)
      {
        return await PublicTool.ReturnError("客服编号无效!");
      }
      else
      {
        return await PublicTool.ReturnSuccess(res);
      }
    }


    /// <summary>
    /// 小程序凭openid获取历史会话和未结束session
    /// </summary>
    /// <param name="openid"></param>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> GetCurrentAsk(string openid)
    {
      var session = GetActiveSession(openid);
      var currentAsk = new AskRecord();
      String sql = "";
      if (string.IsNullOrEmpty(session.Session_id))
      { // 没有进行中的会话
        sql = $@"select 
                  aid,Ask,openid,IsBind,session_id,Sender,Phone,RemoteAccount,RemoteAuth,rate 
                    from z_ask where IsBind <> 'C' and openid='{openid}'";
      }
      else
      { // 凭会话id获取当前提交的问题明细
        sql = $@"select 
                  aid,Ask,openid,IsBind,session_id,Sender,Phone,RemoteAccount,RemoteAuth,rate 
                    from z_ask where session_id ='{session.Session_id}'";
      }
      using (var db = new SyBaseEntities())
      {
        return await PublicTool.ReturnSuccess(db.QueryTable(sql).ToList());
      }
    }

    /// <summary>
    /// 关键字查询已关闭的会话列表
    /// </summary>
    /// <param name="servicerid"></param>
    /// <param name="state"></param>
    /// <param name="keyword"></param>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> GetClosedSessionList(string servicerid, int state, string keyword = "")
    {
      return await PublicTool.ReturnSuccess(MpServiceHelper.GetSessionList(servicerid, state, keyword));
    }

    /// <summary>
    /// 获取access_token
    /// </summary>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> GetMpToken()
    {
      return await PublicTool.ReturnSuccess(MpToken.GetToken());
    }

    /// <summary>
    /// 重置测试数据
    /// </summary>
    /// <returns></returns>
    [HttpGet("[action]")]
    public async Task<IActionResult> Reset()
    {
      using (var db = new SyBaseEntities())
      {
        var sql = "delete z_session";
        db.Execute(sql);
      }
      return await PublicTool.ReturnSuccess("ok");
    }


    /// <summary>
    /// 发送图片
    /// </summary>
    /// <param name="data">图片信息imgBase64，sessionid,msgtype</param>   
    /// <returns></returns>
    [Consumes("application/json")]
    [HttpPost("[action]")]
    public void PushMpImage([FromBody] Dictionary<string, string> data)
    {
      var imgBase64 = data["imgBase64"];
      var sessionid = data["sessionid"];
      var msgtype = data["msgtype"];
      var callBackId = data["callBackId"];
      var res = UploadHelper.Base64SaveAsLocalImg(imgBase64);
      if (!res.IsSuccess) return;
      var saveMsg = new MsgOfSave()
      {
        SessionId = sessionid,
        CustomerId = MpServiceHelper.GetCustomerId(sessionid),
        Dir = "s2c",
        State = 1,
        ToUserName = MpServiceHelper.GetOpenidBySession(sessionid),
        MsgType = msgtype,
        MediaId = res.Url,
        ThumbMediaId = res.Url,
        ThumbUrl = res.Url
      };

      var ReMsg = new MsgToCustomer
      {
        touser = MpServiceHelper.GetOpenidBySession(sessionid),
        msgtype = msgtype
      };

      if (msgtype == "image")
      {
        ReMsg.image = new MsgToCustomerImage { media_id = res.media_id };
      }
      else
      {
        saveMsg.Title = data["title"];
        saveMsg.Content = data["description"];
        //var thumb_media_id = data["thumb_media_id"];
        var c = new MsgToCustomerLink
        {
          title = data["title"],
          description = data["description"],
          thumb_url = res.Url,
          url = res.Url
        };
        ReMsg.link = c;
      }

      var sendmsgsucess = new MsgSendState
      {
        session_id = sessionid,
        callBackId = callBackId,
        state = "sucess"
      };

      var intRes = MpServiceHelper.SendMsgToCustomer(ReMsg);
      if (intRes != 0)
      {
        sendmsgsucess.state = "err";
        sendmsgsucess.statedetail = MpServiceHelper.GetErrText(intRes);
      }
      else
      {
        MpServiceHelper.SaveMsg(saveMsg);
      }

      var clients = WebsocketClientCollection.GetClientList(sessionid);
      WebsocketClientCollection.SendMessageToClientList(clients, "sendmsgstate", JsonConvert.SerializeObject(sendmsgsucess));
    }


    [HttpPost("[action]")]
    public async Task<IActionResult> debug([FromBody] Dictionary<string, string> data)
    {
      return await PublicTool.ReturnSuccess("ok");
    }

    [HttpGet("[action]")]
    public async Task<IActionResult> GetPrintParm(string nid)
    {
      var res = new List<Dictionary<string, dynamic>>();
      using (var db = new SyBaseEntities())
      {
        var sql = $"select * from sys_object where nid={nid}";
        res = db.QueryTable(sql).ToList();
      }
      return await PublicTool.ReturnSuccess(res);
    }


    /// <summary>
    /// 发送小程序卡片
    /// </summary>
    /// <param name="data">图片信息imgBase64，sessionid,msgtype</param>   
    /// <returns></returns>
    [Consumes("application/json")]
    [HttpPost("[action]")]
    public void PushMpCard([FromBody] Dictionary<string, string> data)
    {
      var path = "c:\\a.png";
      var mediaId = UploadHelper.MpUploadMedia(path);
      var sessionid = data["sessionid"];
      var _pagePath = $"pages/pay/index?total={data["total"]}&desc={data["desc"]}&sn={data["sn"]}";

      var ReMsg = new MsgToCustomer
      {
        touser = MpServiceHelper.GetOpenidBySession(sessionid),
        msgtype = "miniprogrampage",
        miniprogrampage = new MsgToCustomerMpLink
        {
          title = data["content"],
          pagepath = _pagePath,
          thumb_media_id = mediaId
        }
      };

      var sendmsgsucess = new MsgSendState
      {
        session_id = sessionid,
        callBackId = data["callBackId"],
        state = "sucess"
      };

      var intRes = MpServiceHelper.SendMsgToCustomer(ReMsg);
      if (intRes != 0)
      {
        sendmsgsucess.state = "err";
        sendmsgsucess.statedetail = MpServiceHelper.GetErrText(intRes);
      }
      else
      {
        var saveMsg = new MsgOfSave()
        {
          Dir = "s2c",
          PagePath = _pagePath,
          Content = data["content"],
          SessionId = sessionid,
          CustomerId = MpServiceHelper.GetCustomerId(sessionid),
          ToUserName = MpServiceHelper.GetOpenidBySession(sessionid),
          MsgType = "miniprogrampage",
          MediaId = "",
          ThumbMediaId = "",
          ThumbUrl = ""
        };
        MpServiceHelper.SaveMsg(saveMsg);
      }

      var clients = WebsocketClientCollection.GetClientList(sessionid);
      WebsocketClientCollection.SendMessageToClientList(clients, "sendmsgstate", JsonConvert.SerializeObject(sendmsgsucess));
    }


    [Consumes("application/json")]
    [HttpPost("[action]")]
    public void PushRateCard([FromBody] Dictionary<string, string> data)
    {
      var path = "c:\\rate.png";
      var mediaId = UploadHelper.MpUploadMedia(path);
      var sessionid = data["sessionid"];
      var aid = MpServiceHelper.GetAskidBySession(sessionid);
      var _pagePath = $"pages/index/addRate?aid={aid}";

      var ReMsg = new MsgToCustomer
      {
        touser = MpServiceHelper.GetOpenidBySession(sessionid),
        msgtype = "miniprogrampage",
        miniprogrampage = new MsgToCustomerMpLink
        {
          title = data["content"],
          pagepath = _pagePath,
          thumb_media_id = mediaId
        }
      };

      var sendmsgsucess = new MsgSendState
      {
        session_id = sessionid,
        callBackId = data["callBackId"],
        state = "sucess"
      };

      var intRes = MpServiceHelper.SendMsgToCustomer(ReMsg);
      if (intRes != 0)
      {
        sendmsgsucess.state = "err";
        sendmsgsucess.statedetail = MpServiceHelper.GetErrText(intRes);
      }
      else
      {
        var saveMsg = new MsgOfSave()
        {
          Dir = "s2c",
          PagePath = _pagePath,
          Content = data["content"],
          SessionId = sessionid,
          CustomerId = MpServiceHelper.GetCustomerId(sessionid),
          ToUserName = MpServiceHelper.GetOpenidBySession(sessionid),
          MsgType = "miniprogrampage",
          MediaId = "",
          ThumbMediaId = "",
          ThumbUrl = ""
        };
        MpServiceHelper.SaveMsg(saveMsg);
      }

      var clients = WebsocketClientCollection.GetClientList(sessionid);
      WebsocketClientCollection.SendMessageToClientList(clients, "sendmsgstate", JsonConvert.SerializeObject(sendmsgsucess));
    }


    /// <summary>
    /// 客服登录验证
    /// </summary>
    /// <param name="data">
    /// UserId：ccode / PassWord:cpassowrd
    /// </param>
    /// <returns></returns>
    [HttpPost("[action]")]
    public async Task<IActionResult> Vaild([FromBody] Dictionary<string, string> data)
    {
      var uid = data["UserId"];
      var res = MpServiceHelper.Vaild(uid, data["PassWord"]);
      if (res.Count < 1)
      {
        return await PublicTool.ReturnError("账号或密码错误！");
      }

      if (WebsocketClientCollection.GetClientList(uid, "O").Count > 0)
      {
        return await PublicTool.ReturnError(res[0]);
      }
      else
      {
        return await PublicTool.ReturnSuccess(res[0]);
      }
    }
    [HttpGet("[action]")]
    public async Task<IActionResult> Test(string openid)
    {
      return await PublicTool.ReturnSuccess(MpServiceHelper.CheckAskBindWithOpenid(openid));
    }
  }
}
